﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Auth.Main;
using System.Data.Entity.Validation;
using EntityFramework.Extensions;
using System.Data.Entity.Migrations;
using Auth.Interface;

namespace Auth.MSSQLStore
{
    public class BaseStore<T> : IRepository<T> where T : BaseEntity
    {
        protected AuthDBContext Context = new AuthDBContext();
        public int Add(T[] entities)
        {
            foreach (var entity in entities)
            {
                entity.IsDeleted = false;
                entity.CreateTime = DateTime.Now;
                Context.Set<T>().Add(entity);
            }

            return Save();
        }

        public int Add(T entity)
        {
            entity.IsDeleted = false;
            entity.CreateTime = DateTime.Now;
            if (entity.EffectTime == DateTime.MinValue) entity.EffectTime = entity.CreateTime;
            if (entity.ExpireTime == DateTime.MinValue) entity.ExpireTime = DateTime.MaxValue;
            Context.Set<T>().Add(entity);
            return Save();
        }

        public int Delete(Expression<Func<T, bool>> exp)
        {
            Context.Set<T>().Where(exp).Delete();
            return Save();
        }

        public int Delete(T entity)
        {
            //remove will remove childs objects
            //if you want to use deleted ,you have mark FK nullable
            Context.Set<T>().Remove(entity);
            return Save();
            //var entry = Context.Entry(entity);
            //entry.State = System.Data.Entity.EntityState.Deleted;
            //return Save();
        }

        public List<T> Find(Expression<Func<T, bool>> exp)
        {
            return Context.Set<T>().Where(exp).ToList();
        }

        public List<T> Find(int pageIndex = 1, int pageSize = 10, string orderBy = "", Expression<Func<T, bool>> exp = null)
        {
            if (pageIndex < 1) pageIndex = 1;
            return Context.Set<T>().Where(exp).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        }
    

        public int GetCount(Expression<Func<T, bool>> exp = null)
        {
            return Context.Set<T>().Where(exp).Count();
        }

        public bool IsExists(Expression<Func<T, bool>> exp)
        {
            return Context.Set<T>().Any(exp);
        }

        public int Save()
        {
            int intEffectRows = -1;

            try
            {
                intEffectRows = Context.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {
                throw new Exception(e.EntityValidationErrors.First().ValidationErrors.First().ErrorMessage);
            }
            return intEffectRows;
        }

        public T Single(Expression<Func<T, bool>> exp)
        {
            return Context.Set<T>().AsNoTracking().FirstOrDefault(exp);
        }

        public int Update(T entity)
        {
            var entry = Context.Entry(entity);
            entry.State = System.Data.Entity.EntityState.Modified;
            return Save();
        }

        public int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> entity)
        {
            return Context.Set<T>().Where(where).Update(entity);
        }

        public int Update(Expression<Func<T, object>> identityExp, T entity)
        {
            Context.Set<T>().AddOrUpdate(identityExp, entity);
            return Save();
        }
    }
}
